package de.gwtprime.server.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cascade;

import de.gwtprime.server.sql.helper.HibernateHelper;
import de.gwtprime.shared.VoteType;

@Entity
@Table(name = "article")
public class Article extends EntityBase{

	/**
	 * SerialVersionUID
	 */
	private static final long serialVersionUID = 1L;

	private String title;

	private String text;
	
	private String image;
	
	private Date datePosted = new Date();

	private List<ArticleSection> sections = new ArrayList<ArticleSection>();
	
	private List<ArticleComment> comments = new ArrayList<ArticleComment>();

	private int numberComments;
	
	/**
	 * Articles are only shown if they are published -> 
	 * They can be edited from admins while they are not published
	 */
	private boolean published = false;
	
	private Article nextArticle;
	
	private Article prevArticle;
	
	@Transient
	private VoteType voteType;
	
	public static Article findArticle(Long id) {
		return HibernateHelper.find(Article.class, id);
	}

	public static List<Article> loadLatestArticles(int numberArticles) {
		//Object o = RequestFactoryServlet.getThreadLocalRequest().getSession().getAttribute("userName");
		return HibernateHelper.getLatestArticles(numberArticles);
	}

	/**
	 * Empty constructor for JPA
	 */
	public Article() {
	}

	public Article(String title, String text) {
		super();
		this.title = title;
		this.text = text;
	}



	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	@Override
	public String toString() {
		return "Article [id=" + getId() + ", title=" + title + ", text=" + text
				+ "]";
	}

	@OneToMany(mappedBy = "article", cascade = CascadeType.ALL)
	public List<ArticleSection> getSections() {
		return sections;
	}

	public void setSections(List<ArticleSection> sections) {
		this.sections = sections;
	}

	public int getNumberComments() {
		return numberComments;
	}

	public void setNumberComments(int numberComments) {
		this.numberComments = numberComments;
	}
	
	public void addSection(ArticleSection section){
		getSections().add(section);
		section.setArticle(this);
	}
	
	public void addSectionAndPersist(ArticleSection section){
		addSection(section);
		persist();
	}

	public void addComment(ArticleComment comment){
		if(getId()==null) persist(); 

		comment.setArticle(this);
		comment.persist();
		
		if(comments.contains(comment)) return;
		comments.add(comment);
		numberComments ++;
		
	}
	
	public ArticleComment addCommentAndPersistImproved(ArticleComment comment){
		
		if(getId()==null) persist(); 
		
		comment = HibernateHelper.merge(comment);
		comment.setArticle(this);
		
		if(comments.contains(comment)) return comment;
		comments.add(comment);
		numberComments ++; 
		persist();
		
		return comment;
		
		
	}
	
	public void addCommentAndPersist(ArticleComment comment){
		addComment(comment);
		persist();
	}
	
	public void addCommentAndPersist(ArticleComment comment, User2 user){
		addComment(comment);
		comment.setUser(user);
		comment.persist();
		persist();
	}
	
	@OneToMany(mappedBy = "article", cascade = CascadeType.REMOVE)
	public List<ArticleComment> getComments() {
		return comments;
	}

	public void setComments(List<ArticleComment> comments) {
		this.comments = comments;
	}

	public void decreaseNumberComments(){
		if(numberComments>0)
			numberComments --;
	}
	
	public void decreaseNumberCommentsAndPersist(){
		decreaseNumberComments();
		persist();
	}

	public Date getDatePosted() {
		return datePosted;
	}

	public void setDatePosted(Date datePosted) {
		this.datePosted = datePosted;
	}
	
	public List<Vote> getAllSectionVotesForUser(User2 user){
		
		return HibernateHelper.queryDBForList(new Vote(), 
				String.format("select v from ArticleSection a " +
				"inner join a.votes v where a.article.id=%s " +
				"AND v.user.id='%s'", getId(), user.getId()));
		
	}
	
	public List<VoteSectionComplete> getAllSectionVotesCompleteForUser(User2 user){
		
		return HibernateHelper.queryDBForList(new VoteSectionComplete(), 
				String.format("select v from ArticleSection a " +
				"inner join a.voteSectionComplete v where a.article.id=%s " +
				"AND v.user.id='%s'", getId(), user.getId()));
		
	}

	public boolean isPublished() {
		return published;
	}

	public void setPublished(boolean published) {
		this.published = published;
	}

	public String getImage() {
		return image;
	}

	public void setImage(String image) {
		this.image = image;
	}

	@OneToOne(cascade=CascadeType.ALL)  
	public Article getNextArticle() {
		return nextArticle;
	}
	public void setNextArticle(Article nextArticle) {
		if(nextArticle==null || nextArticle == this.nextArticle) return;
		this.nextArticle = nextArticle;
		nextArticle.setPrevArticle(this);
	}
	@OneToOne 
	@Cascade({org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.MERGE})
	public Article getPrevArticle() {
		return prevArticle;
	}

	public void setPrevArticle(Article prevArticle) {
		if(prevArticle==null || prevArticle == this.prevArticle) return;
		this.prevArticle = prevArticle;
		prevArticle.setNextArticle(this);
	}
	

}
